#!/usr/bin/python2
import sys
from argparse import ArgumentParser,RawTextHelpFormatter,SUPPRESS
from os import listdir,path,rename,makedirs
from copy import deepcopy
from mutagen.mp3 import MP3
from mutagen.id3 import ID3,APIC,TALB,TCON,TDRC,TIT2,TPE1,TPE2,TRCK,TPOS,TextFrame

#######################################################################################################
### Class Definition

class Tagger:
  '''Tagger takes tags you want set and tags from file, combines and prioritizes yours. Then deletes all tags and adds new ones, but only the tags that matter.'''
  def __init__(self,tagsToSet,mp3):
    self.library='/storage/media/music'
    self.tagsIWant=['TPE1','TALB','TIT2','TRCK','TCON','TDRC','TPE2','APIC']
    self.tagsToSet=tagsToSet
    self.mergedTags={}
    self.filename=mp3
    self.mp3=MP3(mp3)

  #def mergeTags(self):
  # Commented out because it happens always, might as well be part of init
    for t in self.tagsIWant:
      if t in self.tagsToSet.keys():
        self.mergedTags[t]=self.tagsToSet[t]
      elif t in self.mp3.keys():
        self.mergedTags[t]=self.mp3[t]
    for t in self.mergedTags.values():
      if hasattr(t,'encoding'):
        t.encoding=3

  def retag(self):
    for k,v in self.tagsToSet.items():
      self.mp3[k]=v
    for k in self.mp3.keys():
      if k == 'APIC:':
        k='APIC'
      if k not in self.tagsIWant:
        print "Deleting: %-64s %s" % (self.mp3[k].pprint(),self.filename)
        del self.mp3[k]
    self.mp3.save()

  def rename(self):
    title=self.dotit(self.mergedTags['TIT2'].text[0].replace('/','.'))+'.mp3'
    # build /library/artist/album path
    art=self.dotit(self.mergedTags['TPE1'].text[0])
    alb=self.dotit(self.mergedTags['TALB'].text[0])
    newName=path.join(self.library,art,alb,title)
    #print(newName)
    finalDestination=path.join(self.library,art,alb)
    if not path.exists(finalDestination):
      makedirs(finalDestination)
    rename(self.filename,newName)

  def dotit(self,s):
    ns=s.replace(' ','.').replace('_','.')
    lc='.'
    for c in ns:
      if lc=='.':
        c=c.upper
      lc=c
    return ns

#######################################################################################################
### Parse Arguments
isAuto=False
parser=ArgumentParser(description='Clean and retag your mp3s',formatter_class=RawTextHelpFormatter,argument_default=SUPPRESS)
parser.add_argument('-a','--artist', metavar='Cobra Starship',       type=unicode,  dest='TPE1',help='Album Artist')
parser.add_argument('-l','--album',  metavar='Nightshades',          type=unicode,  dest='TALB',help='Album Name')
parser.add_argument('-t','--title',  metavar='Anything For Love',    type=unicode,  dest='TIT2',help='Track Title')
parser.add_argument('-n','--track',  metavar='5',                    type=unicode,  dest='TRCK',help='Track Number')
parser.add_argument('-d','--disk',   metavar='1',                    type=unicode,  dest='TPOS',help='Disk Number')
parser.add_argument('-g','--genre',  metavar='Pop',                  type=unicode,  dest='TCON',help='Genre')
parser.add_argument('-y','--year',   metavar='2011',                 type=unicode,  dest='TDRC',help='Release Year')
parser.add_argument('-A','--contrib',metavar='DJ SamLamb',           type=unicode,  dest='TPE2',help='Contributing Atrist(s)')
parser.add_argument('-p','--pic',    metavar='album.jpg',            type=unicode,  dest='APIC',help='Album Cover')
parser.add_argument('--auto',        action='store_true',                           dest='isAuto',help='Artist/Album deduced from folder Structure')
parser.add_argument('targs',         metavar='Anything.For.Love.mp3',type=unicode,  nargs='*',  help='Name of file(s) or folder(s).',default='.')
args=parser.parse_args().__dict__
targs=args.pop('targs')
tagsToSet={}
for k,v in args.items():
  if TextFrame in globals()[k].__bases__:
    tagsToSet[k]=globals()[k](encoding=3,text=[v])
  if APIC == globals()[k]:
    mimetype=u'image/'+v[-3:]
    picData=open(v,'rb').read()
    tagsToSet[k]=globals()[k](type=3,encoding=3,desc=u'',mime=mimetype,data=picData)

#######################################################################################################
### Find file(s) and Initialize Tagger instance for each

files=[]
mp3s=[]
dirFound=False

def collectMP3s(t):
  targ=t
  if path.exists(targ):
    if path.isfile(targ):
      if targ[-4:].lower() == '.mp3':
        files.append(path.realpath(targ))
    elif path.isdir(targ):
      dirFound=True
      base=path.realpath(targ)
      subtargs=listdir(targ)
      for st in subtargs:
        collectMP3s(base+'/'+st)

for t in targs:
  collectMP3s(t)

if dirFound == True:
  del tagsToSet['TIT2']
  del tagsToSet['TRCK']

for f in files:
  mp3s.append(Tagger(tagsToSet,f))

for m in mp3s:
  #m.mergeTags()
  m.retag()
  m.rename()
